#include <stdio.h>
#include <pthread.h>
#include "otdrtestinterface.h"
#include "printl.h"
extern char *CurrentDateTime(char buf[]);

DeviceInfo_t    dev;
struct fpga_dev *fpgadev;

int ti = 1;
int fi = 0;
int otdrmode = 1;
int apdv;

#ifdef X86
int getTemperature(int *data)
{
    *data = 30000;
    return 0;
}
#endif

int stop(void)
{
    return 0;
}

int AppCallback_test(OtdrTestResult_t *upresult, OtdrTestResult_t *downresult, int en)
{
    int i, valid;
    float *Ai;
    OtdrTestResult_t *caller, *callee;

    if((upresult == NULL) || (downresult == NULL) || (en != E_CMD_OK)){
        printf("AppCallback_test : NULL pointer, or errno = %d\n", en);
    }
    else{
        caller = (OtdrTestResult_t*)upresult;
        callee = (OtdrTestResult_t*)downresult;
        valid = callee->valid;
        Ai = caller->Ai;
        if(en == E_CMD_OK){
            if(valid >= 3){
                memcpy(upresult, downresult, sizeof(OtdrTestResult_t));
            }
            if(valid >= 2){
                for(i = 0; i < caller->tp.DataNum; i++){
                    Ai[i] = callee->Ai[i];
                }
            }
            if(valid >= 1){
                memcpy(&upresult->tp, &downresult->tp, sizeof(downresult->tp));
            }
        }
        caller->Ai = Ai;
    }
    return en;
}


int main_autotest(int argc, char *argv[])
{
    int ret, n;
    OtdrTestParam_t tp, tp2;
    
    tp.ChanNum = 0;
    tp.OtdrMode = 1;
    tp.RefreshPeriod_ms = 1000;
    tp.DataNum = 16000;

    if(argc > 2)    tp.Lambda_nm = atoi(argv[2]);
    else            tp.Lambda_nm = 1550;

    if(argc > 3)    n = atoi(argv[3]);
    else            n = 1;

    tp.MeasureLength_m = 0;
    tp.PulseWidth_ns = 160;
    tp.MeasureTime_ms = 15000;
    tp.n = 1.4685;
    tp.EndThreshold = 5.0;
    tp.NonReflex = 0;
    
    for(fi = 0; fi < n; fi++){
        ret = adaptTestParam(&tp, &tp2, stop, &dev);
        if(ret == E_CMD_OK){
            printf("adaptTestParam : MeasureLength_m = %dm\n",  tp2.MeasureLength_m);
            printf("adaptTestParam : PulseWidth      = %dns\n", tp2.PulseWidth_ns);
        }
        printf("return value %d\n", ret);
    }
    return ret;
}


int main_cs(int argc, char *argv[])
{
    int ret, state, n;
    OtdrTestParam_t tp;
    char ss[2][8] = {"good", "bad"};
    
    tp.ChanNum = 0;
    tp.OtdrMode = 1;
    tp.RefreshPeriod_ms = 1000;
    tp.DataNum = 32000;

    if(argc > 2)    tp.Lambda_nm = atoi(argv[2]);
    else            tp.Lambda_nm = 1550;

    if(argc > 3)    tp.MeasureLength_m = atoi(argv[3]);
    else            tp.MeasureLength_m = 10000;

    if(argc > 4)    n = atoi(argv[4]);
    else            n = 1;

    tp.PulseWidth_ns = 80;
    tp.MeasureTime_ms = 15000;
    tp.n = 1.4685;
    tp.EndThreshold = 5.0;
    tp.NonReflex = 0;
    
    for(fi = 0; fi < n; fi++){
        ret = getConnectState(&tp, &state, stop, &dev);
        if(ret == E_CMD_OK){
            printf("getConnectState result: %s\n", ss[state-1]);
        }
        printf("return value %d\n", ret);
    }
    return ret;
}

int main_concat(int argc, char *argv[])
{
    int ret, n;
    OtdrTestParam_t tp;
    ConcatParam_t cp;
    
    tp.ChanNum = 0;
    tp.OtdrMode = 1;
    tp.RefreshPeriod_ms = 1000;
    tp.DataNum = 32000;

    if(argc > 2)    tp.Lambda_nm = atoi(argv[2]);
    else            tp.Lambda_nm = 1550;

    if(argc > 3)    tp.MeasureLength_m = atoi(argv[3]);
    else            tp.MeasureLength_m = 100000;

    if(argc > 4)    tp.PulseWidth_ns = atoi(argv[4]);
    else            tp.PulseWidth_ns = 1280;

    if(argc > 5)    n = atoi(argv[5]);
    else            n = 1;

    tp.MeasureTime_ms = 15000;
    tp.n = 1.4685;
    tp.EndThreshold = 5.0;
    tp.NonReflex = 0;
    
    for(fi = 0; fi < n; fi++){
        printf("=========== test %d ==============\n", fi);
        ret = getConcat(&tp, &cp, stop, &dev);
        if(ret == E_CMD_OK){
            printf("getConcat result %dnm%dkm%dns: powermode = %d, concatpoint = %d, lp = %d, lr = %d, hp = %d, hr = %d\n", \
                    tp.Lambda_nm, tp.MeasureLength_m/1000, tp.PulseWidth_ns, \
                    cp.PowerMode, cp.ConcatPoint, cp.LowPower, cp.LowRcv, cp.HighPower, cp.HighRcv);
        }
        else    printf("return value %d\n", ret);
    }
    return ret;
}

int main_getTemp(int argc, char *argv[])
{
    int i, n, t;

    if(argc > 2){
        n = atoi(argv[2]);
    }
    else    n = 20;

    for(i = 0; i < n; i++){
        getTemperature(&t);
        printf("%d\n", t);
        usleep(100*1000);
    }
    return 0;

}

int main_vfl(int argc, char *argv[])
{
    if(argc != 3){
        printf("Usage : %s vfl [off | on | blink]\n");
        printf("Usage : %s vfl [0 | 1 | 2]\n");
        return -1;
    }

    if(!strcmp(argv[2], "off")   || !strcmp(argv[2], "0"))    closeVFL(&dev);
    if(!strcmp(argv[2], "on")    || !strcmp(argv[2], "1"))    openVFL(&dev);
    if(!strcmp(argv[2], "blink") || !strcmp(argv[2], "2"))    twinkleVFL(&dev);
    return 0;
}

// otdr test
int main_otdrtest(int argc, char *argv[])
{
    extern int startTestAsync(void *tp, int (*AppCallback_test)(void *, void *, int), void *OtdrTestResult, int (*stop)(void), void *device);
    void printHelp(char *programname, int id);
    char  timebuf[32];
    int i, j, ret, n;
    float abcoef, abloss, al[8], bl[8];
    int ap[8] = {0, 50, 103, 104, 105, 9742, 11000, 11816};
    int bp[8] = {60, 5000, 9741, 9742, 11815, 11816, 11817, 20000};

    OtdrTestParam_t tp;
    OtdrTestResult_t tr;

    tr.Ai = (float*)malloc(32000 * sizeof(float));
    
    otdrmode = 1;

    tp.ChanNum = 0;
    tp.OtdrMode = otdrmode;
    tp.RefreshPeriod_ms = 1000;
    tp.DataNum = 16000;
    tp.slice_ms = 1000;

    tp.n = 1.4685;
    tp.EndThreshold = 5.0;
    tp.NonReflex = 0;

    if(argc <= 2){
        printHelp(argv[0], 1);
        return 0;
    }

    if(argc > 2)    tp.Lambda_nm = atoi(argv[2]);
    else            tp.Lambda_nm = 1550;

    if(argc > 3)    tp.MeasureLength_m = atoi(argv[3]);
    else            tp.MeasureLength_m = 30000;

    if(argc > 4)    tp.PulseWidth_ns = atoi(argv[4]);
    else            tp.PulseWidth_ns = 160;

    if(argc > 5)    tp.MeasureTime_ms = 1000 * atoi(argv[5]);
    else            tp.MeasureTime_ms = 5000;
    
    if(argc > 6)    n = atoi(argv[6]);
    else            n = 1;
    
    if(argc > 7)    apdv = atoi(argv[7]);
    else            apdv = 0;

    for(ti = 0; ti < n; ti++){
        fi = 0;
        printf("=========== test %d at time : %s ==============\n", fi, CurrentDateTime(timebuf));
        //ret = startTest(&tp, AppCallback_test, &tr, stop, &dev);
        ret = startTest(&tp, AppCallback_test, &tr, stop, &dev);
        if(ret == E_CMD_OK){
            printf("**** StartTest result: %dnm%dkm%dns%ds\n", tr.tp.Lambda_nm, tr.tp.MeasureLength_m/1000, tr.tp.PulseWidth_ns, tr.tp.MeasureTime_ms/1000);
            printf("****                   FiberLen = %.2fm, FiberLoss = %.3fdB, FiberAttenCoef = %.3fdB/km\n",
                    tr.FiberLen, tr.FiberLoss, tr.FiberAttenCoef);
            printf("finished at time : %s ==============\n", CurrentDateTime(timebuf));
        }
        printf("return value %d\n", ret);
    }

    free(tr.Ai);
    return ret;
}

void printHelp(char *programname, int id)
{
    if(id == 0){
        printf("otdr-algo-test tool : utilities to test otdr-algo.\n");
        printf("Usage : %s autotest | cs | concat | otdrtest\n", programname);
        printf("here, toolname is one of [autotest, cs, concat, otdrtest]\n");
    }
    else{   // otdrtest help
        printf("Usage : %s otdrtest 波长(nm) 量程(m) 脉宽(ns) 测量时间(s)\n", programname);
        printf("如 : %s otdrtest 1550 30000 160 5 --> 以1550nm/30km/160ns的条件测量5秒\n", programname);
    }
}


int main(int argc, char *argv[])
{
    int result, n;

    if(argc == 1){
        printHelp(argv[0], 0);
        return 0;
    }
    EN_OTDR_DBG_LEVEL(BIT_RX);
    EN_OTDR_DBG_LEVEL(BIT_TX);

#if DATA_SPI
    result = fpga_open("/dev/spidev3.0", &fpgadev, 5000000);
    if(result == 0)         printf("fpga_open success\n");
    else{
        if(result == -1)        printf("fpga_open bus error\n");
        else if(result == -2)   printf("fpga_open unknown devID\n");

        return -1;
    }
#endif
    pthread_mutex_init(&dev.mutex_fpga, NULL);
    dev.fpga= fpgadev;

    if(strcmp(argv[1], "autotest") == 0)        main_autotest(argc, argv);
    else if(strcmp(argv[1], "cs") == 0)         main_cs(argc, argv);
    else if(strcmp(argv[1], "concat") == 0)     main_concat(argc, argv);
    else if(strcmp(argv[1], "otdrtest") == 0)   main_otdrtest(argc, argv);
    else if(strcmp(argv[1], "vfl") == 0)        main_vfl(argc, argv);
    else if(strcmp(argv[1], "temp") == 0)       main_getTemp(argc, argv);
    else    printHelp(argv[0], 0);

#if DATA_SPI
    fpga_close(fpgadev);
#endif

    return 0;
}

